<!DOCTYPE html>
<!--
@license
Copyright (C) 2017 The Android Open Source Project

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->

<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
<title>gr-gpg-editor</title>

<script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>

<script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
<script src="/bower_components/web-component-tester/browser.js"></script>
<link rel="import" href="../../../test/common-test-setup.html"/>
<link rel="import" href="gr-gpg-editor.html">

<script>void(0);</script>

<test-fixture id="basic">
  <template>
    <gr-gpg-editor></gr-gpg-editor>
  </template>
</test-fixture>

<script>
  suite('gr-gpg-editor tests', () => {
    let element;
    let keys;

    setup(done => {
      const fingerprint1 = '0192 723D 42D1 0C5B 32A6  E1E0 9350 9E4B AFC8 A49B';
      const fingerprint2 = '0196 723D 42D1 0C5B 32A6  E1E0 9350 9E4B AFC8 A49B';
      keys = {
        AFC8A49B: {
          fingerprint: fingerprint1,
          user_ids: [
            'John Doe john.doe@example.com',
          ],
          key: '-----BEGIN PGP PUBLIC KEY BLOCK-----' +
               '\nVersion: BCPG v1.52\n\t<key 1>',
          status: 'TRUSTED',
          problems: [],
        },
        AED9B59C: {
          fingerprint: fingerprint2,
          user_ids: [
            'Gerrit gerrit@example.com',
          ],
          key: '-----BEGIN PGP PUBLIC KEY BLOCK-----' +
               '\nVersion: BCPG v1.52\n\t<key 2>',
          status: 'TRUSTED',
          problems: [],
        },
      };

      stub('gr-rest-api-interface', {
        getAccountGPGKeys() { return Promise.resolve(keys); },
      });

      element = fixture('basic');

      element.loadData().then(() => { flush(done); });
    });

    test('renders', () => {
      const rows = Polymer.dom(element.root).querySelectorAll('tbody tr');

      assert.equal(rows.length, 2);

      let cells = rows[0].querySelectorAll('td');
      assert.equal(cells[0].textContent, 'AFC8A49B');

      cells = rows[1].querySelectorAll('td');
      assert.equal(cells[0].textContent, 'AED9B59C');
    });

    test('remove key', done => {
      const lastKey = keys[Object.keys(keys)[1]];

      const saveStub = sinon.stub(element.$.restAPI, 'deleteAccountGPGKey',
          () => { return Promise.resolve(); });

      assert.equal(element._keysToRemove.length, 0);
      assert.isFalse(element.hasUnsavedChanges);

      // Get the delete button for the last row.
      const button = Polymer.dom(element.root).querySelector(
          'tbody tr:last-of-type td:nth-child(6) gr-button');

      MockInteractions.tap(button);

      assert.equal(element._keys.length, 1);
      assert.equal(element._keysToRemove.length, 1);
      assert.equal(element._keysToRemove[0], lastKey);
      assert.isTrue(element.hasUnsavedChanges);
      assert.isFalse(saveStub.called);

      element.save().then(() => {
        assert.isTrue(saveStub.called);
        assert.equal(saveStub.lastCall.args[0], Object.keys(keys)[1]);
        assert.equal(element._keysToRemove.length, 0);
        assert.isFalse(element.hasUnsavedChanges);
        done();
      });
    });

    test('show key', () => {
      const openSpy = sinon.spy(element.$.viewKeyOverlay, 'open');

      // Get the show button for the last row.
      const button = Polymer.dom(element.root).querySelector(
          'tbody tr:last-of-type td:nth-child(4) gr-button');

      MockInteractions.tap(button);

      assert.equal(element._keyToView, keys[Object.keys(keys)[1]]);
      assert.isTrue(openSpy.called);
    });

    test('add key', done => {
      const newKeyString =
          '-----BEGIN PGP PUBLIC KEY BLOCK-----' +
          '\nVersion: BCPG v1.52\n\t<key 3>';
      const newKeyObject = {
        ADE8A59B: {
          fingerprint: '0194 723D 42D1 0C5B 32A6  E1E0 9350 9E4B AFC8 A49B',
          user_ids: [
            'John john@example.com',
          ],
          key: newKeyString,
          status: 'TRUSTED',
          problems: [],
        },
      };

      const addStub = sinon.stub(element.$.restAPI, 'addAccountGPGKey',
          () => { return Promise.resolve(newKeyObject); });

      element._newKey = newKeyString;

      assert.isFalse(element.$.addButton.disabled);
      assert.isFalse(element.$.newKey.disabled);

      element._handleAddKey().then(() => {
        assert.isTrue(element.$.addButton.disabled);
        assert.isFalse(element.$.newKey.disabled);
        assert.equal(element._keys.length, 2);
        done();
      });

      assert.isTrue(element.$.addButton.disabled);
      assert.isTrue(element.$.newKey.disabled);

      assert.isTrue(addStub.called);
      assert.deepEqual(addStub.lastCall.args[0], {add: [newKeyString]});
    });

    test('add invalid key', done => {
      const newKeyString = 'not even close to valid';

      const addStub = sinon.stub(element.$.restAPI, 'addAccountGPGKey',
          () => { return Promise.reject(new Error('error')); });

      element._newKey = newKeyString;

      assert.isFalse(element.$.addButton.disabled);
      assert.isFalse(element.$.newKey.disabled);

      element._handleAddKey().then(() => {
        assert.isFalse(element.$.addButton.disabled);
        assert.isFalse(element.$.newKey.disabled);
        assert.equal(element._keys.length, 2);
        done();
      });

      assert.isTrue(element.$.addButton.disabled);
      assert.isTrue(element.$.newKey.disabled);

      assert.isTrue(addStub.called);
      assert.deepEqual(addStub.lastCall.args[0], {add: [newKeyString]});
    });
  });
</script>
